package com.casework

import grails.plugin.spock.IntegrationSpec
import org.joda.time.LocalDate
import spock.lang.Shared
import spock.lang.Unroll
import static com.casework.CompetitionConcern.*

class SearchControllerSpec extends IntegrationSpec {

    @Shared LocalDate now
    @Shared SearchController controller


    Map renderMap


    void setup() {
        now = new LocalDate()
        controller = new SearchController()
        controller.metaClass.render = {Map m ->
            renderMap = m
        }
    }

    void cleanup() {
        LegalCase.list()*.delete()
    }

    def "test controller"() {
        given:
        new LegalCase(ecNumber: 123, phase: 1).save(failOnError: true)

        when:
        controller.search(new SearchCommand(ecNumberStr: '123'))

        then:
        println renderMap
    }

    @Unroll('Search for #ecNumberStr should return #size number of items')
    def "Search by ec number"() {
        given:
        cases.each {it.phase = 1; it.save(failOnError: true)}

        when:
        controller.search(new SearchCommand(ecNumberStr: ecNumberStr))

        then:
        renderMap.model.legalCaseInstanceList.size() == size

        where:
        cases                             | ecNumberStr   | size
        []                                | '123'         | 0
        [new LegalCase(ecNumber: 123)]    | '123'         | 1
        [new LegalCase(ecNumber: 123)]    | 'M123'        | 1
        [new LegalCase(ecNumber: 123123)] | 'M123 123'    | 1
        [new LegalCase(ecNumber: 123)]    | 'onetwothree' | 1  //since nothing is passed in it returns all legal cases
    }

    @Unroll('Decisiondate of #fromDecisionYear should return a size of #size')
    def "Search by decision date"() {
        given:
        cases.each {it.phase = 1; it.ecNumber = 1; it.save(failOnError: true)}

        when:
        controller.search(new SearchCommand(fromDecisionYear: now.getYear()))

        then:
        renderMap.model.legalCaseInstanceList.size() == size

        where:
        cases                                            | size
        []                                               | 0
        [new LegalCase(decisionDate: now.plusYears(1))]  | 1
        [new LegalCase(decisionDate: now)]               | 1
        [new LegalCase(decisionDate: now.minusYears(1))] | 0
    }


    @Unroll("When #searchPhase passed in it should return size of #size")
    def "Filter by list of phases"() {
        given:
        cases.each {it.ecNumber = 1; it.save(failOnError: true)}

        when:
        controller.search(new SearchCommand(phaseStr: searchPhase))

        then:
        renderMap.model.legalCaseInstanceList.size() == size

        where:
        cases                     | size | searchPhase
        []                        | 0    | ["0"]
        [new LegalCase(phase: 1)] | 0    | ["2"]
        [new LegalCase(phase: 2)] | 1    | ["2"]
    }

    @Unroll("When #searchRelativeSO passed in it should return size of #size")
    def "Filter by Relative SO"() {
        given:
        cases.each {it.ecNumber = 1; it.phase = 1; it.save(failOnError: true)}

        when:
        controller.search(new SearchCommand(relativeToSOStr: searchRelativeSO))

        then:
        renderMap.model.legalCaseInstanceList.size() == size

        where:
        cases                                            | size | searchRelativeSO
        []                                               | 0    | [RelativeToSO.Post.toString()]
        [new LegalCase(relativeToSO: RelativeToSO.Post)] | 1    | [RelativeToSO.Post.toString()]
        [new LegalCase(relativeToSO: RelativeToSO.Pre)]  | 1    | [RelativeToSO.Pre.toString()]
        [new LegalCase(relativeToSO: RelativeToSO.Post)] | 0    | [RelativeToSO.Pre.toString()]
        [new LegalCase(relativeToSO: null)]              | 0    | [RelativeToSO.Pre.toString()]
    }

    @Unroll("When cluster sale is set to #cSale and we search for #searchClusterSale size should be #size")
    def "Filter by Cluster Sale"() {
        given:
        LegalCase aCase = new LegalCase(ecNumber: 1, phase: 1).save()
        aCase.addToMeasures(new Measure(clusterSale: cSale)).save()

        when:
        controller.search(new SearchCommand(clusterSaleStr: searchClusterSale))

        then:
        renderMap.model.legalCaseInstanceList.size() == size

        where:
        cSale       | searchClusterSale        | size
        YesNoNA.Yes | [YesNoNA.No.toString()]  | 0
        YesNoNA.Yes | [YesNoNA.Yes.toString()] | 1
        YesNoNA.No  | [YesNoNA.Yes.toString()] | 0
        null        | [YesNoNA.Yes.toString()] | 0
        YesNoNA.No  | [YesNoNA.No.toString()]  | 1
    }

    @Unroll("When alternative remedy is set to #aRemedy and we search for #searchAlternativeRemedy size should be #size")
    def "Filter by Alternative remedy"() {
        given:
        LegalCase aCase = new LegalCase(ecNumber: 1, phase: 1).save()
        aCase.addToMeasures(new Measure(alternativeRemedy: aRemedy)).save()

        when:
        controller.search(new SearchCommand(alternativeRemedyStr: searchAlternativeRemedy))

        then:
        renderMap.model.legalCaseInstanceList.size() == size

        where:
        aRemedy     | searchAlternativeRemedy  | size
        YesNoNA.Yes | [YesNoNA.No.toString()]  | 0
        YesNoNA.Yes | [YesNoNA.Yes.toString()] | 1
        YesNoNA.No  | [YesNoNA.No.toString()]  | 1
        YesNoNA.No  | [YesNoNA.Yes.toString()] | 0
        null        | [YesNoNA.Yes.toString()] | 0
    }

    @Unroll("When criteria is #criteria and we search for #searchCriteria size should be #size")
    def "Filter by purchaser criteria"() {
        given:
        LegalCase aCase = new LegalCase(ecNumber: 1, phase: 1).save()
        aCase.addToMeasures(new Measure(purchaserCriteria: criteria)).save()

        when:
        controller.search(new SearchCommand(purchaserCriteriaStrs: [searchCriteria]))

        then:
        renderMap.model.legalCaseInstanceList.size() == size

        where:
        criteria                                 | searchCriteria                                      | size
        PurchaserCriteria.Fix_It_First           | PurchaserCriteria.Fix_It_First.toString()           | 1
        PurchaserCriteria.Purchaser_Requirements | PurchaserCriteria.Purchaser_Requirements.toString() | 1
        PurchaserCriteria.Up_Front_Buyer         | PurchaserCriteria.Up_Front_Buyer.toString()         | 1
        PurchaserCriteria.Fix_It_First           | PurchaserCriteria.Up_Front_Buyer.toString()         | 0
        null                                     | PurchaserCriteria.Up_Front_Buyer.toString()         | 0
    }

    def "Filter by purchase criteria when there are more than one criteria"() {
        given:
        LegalCase aCase = new LegalCase(ecNumber: 1, phase: 1).save()
        aCase.addToMeasures(new Measure(purchaserCriteria: PurchaserCriteria.Fix_It_First)).save()
        LegalCase aCase2 = new LegalCase(ecNumber: 1, phase: 1).save()
        aCase2.addToMeasures(new Measure(purchaserCriteria: PurchaserCriteria.Up_Front_Buyer)).save()
        LegalCase aCase3 = new LegalCase(ecNumber: 1, phase: 1).save()
        aCase3.addToMeasures(new Measure(purchaserCriteria: PurchaserCriteria.Purchaser_Requirements)).save()

        when:
        controller.search(new SearchCommand(purchaserCriteriaStrs: [PurchaserCriteria.Fix_It_First.toString(), PurchaserCriteria.Up_Front_Buyer.toString()]))

        then:
        renderMap.model.legalCaseInstanceList.size() == 2
        !renderMap.model.legalCaseInstanceList.any {LegalCase legalCase -> legalCase.measures[0].purchaserCriteria == PurchaserCriteria.Purchaser_Requirements}
    }

    def "filter by short nace description"() {
        given:
        LegalCase aCase = new LegalCase(ecNumber: 1, phase: 1).save()
        NaceCategory naceCategory = new NaceCategory(shortDescription: 'nace category').save()
        Nace nace = new Nace(description: "nace", naceCategory: naceCategory, code: '123').save(failOnError: true)
        LegalCaseNaceFullDescription.create(aCase, nace, true)


        when:
        controller.search(new SearchCommand(shortNace: searchTerm))

        then:
        renderMap.model.legalCaseInstanceList.size() == size

        where:
        searchTerm        | size
        ["nothing"]       | 0
        ['nace category'] | 1
    }

    @Unroll("When cc is #competitionConcerns and we search for #searchTerm size should be #size")
    def "Filter by Competition Concern"() {
        given:
        LegalCase aCase = new LegalCase(ecNumber: 1, phase: 1).save()

        competitionConcerns.each {
            Measure measure = new Measure(competitionConcern: it, purchaserCriteria: PurchaserCriteria.Fix_It_First)
            aCase.addToMeasures(measure).save(failOnError: true, flush: true)
        }

        when:
        controller.search(new SearchCommand(competitionConcern: searchTerm, purchaserCriteriaStrs: [PurchaserCriteria.Fix_It_First.toString()], cases: false))

        then:
        renderMap.model.measureInstanceTotal == size

        where:
        searchTerm              | size | competitionConcerns
        [Horizontal.toString()] | 2    | [Horizontal, Horizontal]
        [Vertical.toString()]   | 1    | [Vertical, Horizontal]
        [Mixed.toString()]      | 0    | [Vertical, Horizontal]
        [Mixed.toString()]      | 1    | [Mixed]
        [Vertical.toString()]   | 2    | [Vertical, Vertical]
        [Vertical.toString()]   | 1    | [Vertical]
        [null]                  | 1    | [Vertical]

    }
}
